"""
AIPPT PPT Generation Router
Provides API endpoints for AIPPT PPT template and generation operations
"""
from fastapi import APIRouter, HTTPException, Query, Body, UploadFile, File, Form
from fastapi.responses import FileResponse
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field

from src.llm.aippt_app.services import (
    TemplateService,
    PPTGenerationService,
    PPTManagementService
)
from src.llm.aippt_app.services.image_cache_service import ImageCacheService
from src.middleware.response_formatter import create_success_response, create_error_response


router = APIRouter(prefix="/api/v1/aippt", tags=["AIPPT"])


# ==================== Helper Functions ====================

def handle_api_response(result: Dict[str, Any], success_message: str) -> Dict[str, Any]:
    """
    Handle API response and convert to standardized format

    Args:
        result: API response from AIPPT service
        success_message: Message to return on success

    Returns:
        Standardized response
    """
    # Check if API returned success (code == 0)
    if result.get('code') == 0:
        return create_success_response(result.get('data'), success_message)
    else:
        # API returned error
        error_message = result.get('message', 'Unknown error from AIPPT API')
        error_code = result.get('code', -1)
        return create_error_response(f"API Error (code {error_code}): {error_message}", 500)


# ==================== Request Models ====================

class TemplateListRequest(BaseModel):
    """List templates request"""
    current: int = Field(1, ge=1, description="Current page number")
    size: int = Field(10, ge=1, le=100, description="Page size")
    type: Optional[int] = Field(None, description="Template type: 1=platform, 4=custom user templates")
    category: Optional[str] = Field(None, description="Filter by category")
    style: Optional[str] = Field(None, description="Filter by style")
    themeColor: Optional[str] = Field(None, description="Filter by theme color")
    layout: Optional[str] = Field(None, description="Filter by layout")


class CreateTaskRequest(BaseModel):
    """Create PPT task request"""
    content: str = Field(..., description="Content for PPT generation")
    task_type: int = Field(1, description="Task type: 1=smart generation, 6=paste text, etc.")


class GenerateContentRequest(BaseModel):
    """Generate content request"""
    task_id: str = Field(..., description="Task ID from create task")
    template_id: Optional[str] = Field(None, description="Template ID to use")
    prompt: Optional[str] = Field(None, description="Additional generation prompt")
    audience: Optional[str] = Field(None, description="Target audience")
    lang: str = Field("zh", description="Language code")
    page_count: int = Field(10, ge=1, le=50, description="Number of pages")


class ModifyContentRequest(BaseModel):
    """Modify content request"""
    task_id: str = Field(..., description="Task ID")
    instruction: str = Field(..., description="Modification instruction")


class GeneratePPTFileRequest(BaseModel):
    """Generate PPT file request"""
    task_id: str = Field(..., description="Task ID")
    markdown: str = Field(..., description="Markdown content")
    template_id: str = Field(..., description="Template ID to use")


class CombinedGeneratePPTRequest(BaseModel):
    """Combined create task + generate PPT request"""
    task_type: int = Field(..., description="Task type: 1=smart generation, 2=upload file, 3=mind map, 4=word to ppt, 5=web link, 6=paste text, 7=markdown")
    content: Optional[str] = Field(None, description="Content based on task type")
    markdown: str = Field(..., description="Markdown outline and content for PPT generation")
    template_id: str = Field(..., description="Template ID to use")


class CreatePPTCompleteRequest(BaseModel):
    """Complete PPT creation request (one-step)"""
    content: str = Field(..., description="Input text content")
    template_id: str = Field(..., description="Template ID to use")
    prompt: Optional[str] = Field(None, description="Additional prompt")
    page_count: int = Field(10, ge=1, le=50, description="Number of pages")
    lang: str = Field("zh", description="Language code")


# ==================== Template Routes ====================

@router.get("/down", summary="Download and cache template cover image")
async def download_template_cover(
    url: str = Query(..., description="Cover URL from template list")
):
    """
    Download and cache template cover image

    This endpoint:
    1. Checks if the image is already cached locally
    2. If cached, returns the local file directly
    3. If not cached, downloads from the original URL with authentication
    4. Saves to cache and returns the file

    The cache ID is automatically extracted from the URL or generated from URL hash.

    Args:
        url: Original cover URL (e.g., from template.coverUrl)

    Returns:
        Image file (PNG/JPG)

    Example:
        /api/v1/aippt/down?url=https://chatmee.cn/api/common/oss/meta-doc/ppt_template/1940697631068151808.png
    """
    try:
        # Initialize image cache service
        cache_service = ImageCacheService()

        # Get cached image or download if not exists
        local_path = cache_service.get_cached_image(url)

        # Determine media type from file extension
        if local_path.endswith('.jpg') or local_path.endswith('.jpeg'):
            media_type = "image/jpeg"
        elif local_path.endswith('.png'):
            media_type = "image/png"
        else:
            media_type = "application/octet-stream"

        # Extract filename from path
        import os
        filename = os.path.basename(local_path)

        # Return file
        return FileResponse(
            path=local_path,
            media_type=media_type,
            filename=filename
        )

    except Exception as e:
        return create_error_response(str(e), 500)


@router.get("/templates/options", summary="Get template filter options")
async def get_template_options():
    """
    Get available template filter options

    Returns:
        Theme colors, categories, styles, and layout options
    """
    try:
        service = TemplateService()
        result = service.get_filter_options()
        return handle_api_response(result, "Successfully retrieved template options")
    except Exception as e:
        return create_error_response(str(e), 500)


@router.get("/templates/random", summary="Get random templates")
async def get_random_templates(
    count: int = Query(5, ge=1, le=20, description="Number of templates to fetch"),
    lang: str = Query("zh", description="Language code")
):
    """
    Get random templates

    Args:
        count: Number of templates
        lang: Language code

    Returns:
        List of random templates
    """
    try:
        service = TemplateService()
        templates = service.get_random_templates(count, lang)
        return create_success_response(templates, f"Successfully retrieved {len(templates)} templates")
    except Exception as e:
        return create_error_response(str(e), 500)


@router.post("/templates", summary="List templates with filters")
async def list_templates(
    request: TemplateListRequest,
    lang: str = Query("zh", description="Language code")
):
    """
    List templates with pagination and filters

    **参数说明**:
    - type: 模板类型（必传）- 1=系统平台模板, 4=用户自定义模板
    - category, style, themeColor, layout: 可选筛选条件

    Args:
        request: Template list request with filters
            - type: 1 for platform templates, 4 for custom user templates
            - category, style, themeColor, layout: filter criteria
        lang: Language code

    Returns:
        Paginated template list
    """
    try:
        service = TemplateService()

        # 使用正确的API格式
        result = service.list_templates(
            current=request.current,
            size=request.size,
            template_type=request.type if request.type is not None else 1,  # type默认为1
            category=request.category,
            style=request.style,
            theme_color=request.themeColor,
            layout=request.layout,
            lang=lang
        )

        # 检查API响应
        if result.get('code') == 0:
            # 成功响应
            return create_success_response(
                {
                    "list": result.get('data', []),
                    "total": result.get('total', 0),
                    "page": request.current,
                    "pageSize": request.size
                },
                result.get('message', 'Successfully retrieved templates')
            )
        else:
            # API返回错误
            return create_error_response(
                result.get('message', 'Failed to retrieve templates'),
                500
            )

    except Exception as e:
        return create_error_response(str(e), 500)


# ==================== PPT Generation Routes (V2 API) ====================

@router.post("/generation/task/create", summary="Create PPT generation task (Enhanced)")
async def create_task_enhanced(
    task_type: int = Form(..., description="Task type: 1=smart generation, 2=upload file, 3=mind map, 4=word to ppt, 5=web link, 6=paste text, 7=markdown"),
    content: Optional[str] = Form(None, description="Content based on task type"),
    files: Optional[List[UploadFile]] = File(None, description="Files for upload (type 2, 3, 4)")
):
    """
    Create a new PPT generation task with full support for all types

    **Task Types:**
    - 1: Smart Generation (theme/requirements) - content required
    - 2: Upload File - files required (multiple supported)
    - 3: Mind Map - files required (xmind/mm/md, single file)
    - 4: Word to PPT - files required (doc/docx, single file)
    - 5: Web Link - content required (http/https URL)
    - 6: Paste Text - content required (up to 20000 chars)
    - 7: Markdown Outline - content required (markdown format)

    **File Support:**
    - Formats: doc/docx/pdf/ppt/pptx/txt/md/xls/xlsx/csv/html/epub/mobi/xmind/mm
    - Max 5 files, total size <= 50M

    Args:
        task_type: Type of PPT generation task (1-7)
        content: Text content (required for types 1, 5, 6, 7)
        files: Uploaded files (required for types 2, 3, 4)

    Returns:
        Task ID for tracking the generation process
    """
    try:
        # Validate input based on task type
        if task_type in [1, 5, 6, 7] and not content:
            return create_error_response(
                f"Content is required for task type {task_type}",
                400
            )

        if task_type in [2, 3, 4] and not files:
            return create_error_response(
                f"Files are required for task type {task_type}",
                400
            )

        # Validate file constraints
        if files:
            if len(files) > 5:
                return create_error_response(
                    "Maximum 5 files allowed",
                    400
                )

            # Check file types for specific task types
            if task_type == 3:
                # Mind map - only one file, xmind/mm/md
                if len(files) > 1:
                    return create_error_response(
                        "Mind map upload only supports one file",
                        400
                    )
                allowed_ext = ['.xmind', '.mm', '.md']
                filename = files[0].filename.lower()
                if not any(filename.endswith(ext) for ext in allowed_ext):
                    return create_error_response(
                        f"Mind map file must be xmind, mm, or md format",
                        400
                    )

            elif task_type == 4:
                # Word to PPT - only one file, doc/docx
                if len(files) > 1:
                    return create_error_response(
                        "Word to PPT only supports one file",
                        400
                    )
                allowed_ext = ['.doc', '.docx']
                filename = files[0].filename.lower()
                if not any(filename.endswith(ext) for ext in allowed_ext):
                    return create_error_response(
                        f"Word file must be doc or docx format",
                        400
                    )

        service = PPTGenerationService()

        # Handle file upload if present
        file_tuples = None
        if files:
            # Convert UploadFile to format expected by API client
            file_tuples = []
            for file in files:
                file_content = await file.read()
                file_tuples.append((
                    'file',
                    (file.filename, file_content, file.content_type)
                ))

        # Call service to create task
        task_id = service.create_task_from_text(
            content=content,
            task_type=task_type,
            files=file_tuples
        )

        return create_success_response(
            {"task_id": task_id},
            "Task created successfully"
        )

    except Exception as e:
        return create_error_response(str(e), 500)


@router.get("/generation/options", summary="Get generation options")
async def get_generation_options(
    lang: str = Query("zh", description="Language code")
):
    """
    Get available generation options

    Args:
        lang: Language code

    Returns:
        Generation options (audience, languages, page counts, styles)
    """
    try:
        service = PPTGenerationService()
        result = service.get_generation_options(lang)
        return handle_api_response(result, "Successfully retrieved generation options")
    except Exception as e:
        return create_error_response(str(e), 500)


@router.post("/generation/task", summary="Create PPT generation task")
async def create_task(request: CreateTaskRequest):
    """
    Create a new PPT generation task

    Args:
        request: Task creation request

    Returns:
        Task ID
    """
    try:
        service = PPTGenerationService()
        task_id = service.create_task_from_text(
            content=request.content,
            task_type=request.task_type
        )
        return create_success_response(
            {"task_id": task_id},
            "Task created successfully"
        )
    except Exception as e:
        return create_error_response(str(e), 500)


@router.post("/generation/content", summary="Generate PPT content")
async def generate_content(request: GenerateContentRequest):
    """
    Generate PPT outline and content

    Args:
        request: Content generation request

    Returns:
        Generated content with markdown outline
    """
    try:
        service = PPTGenerationService()
        result = service.generate_ppt_content(
            task_id=request.task_id,
            prompt=request.prompt,
            template_id=request.template_id,
            audience=request.audience,
            lang=request.lang,
            page_count=request.page_count
        )
        return handle_api_response(result, "Content generated successfully")
    except Exception as e:
        return create_error_response(str(e), 500)


@router.post("/generation/content/modify", summary="Modify PPT content")
async def modify_content(request: ModifyContentRequest):
    """
    Modify existing PPT content based on instruction

    Args:
        request: Modification request

    Returns:
        Modified content
    """
    try:
        service = PPTGenerationService()
        result = service.modify_content(
            task_id=request.task_id,
            instruction=request.instruction
        )
        return handle_api_response(result, "Content modified successfully")
    except Exception as e:
        return create_error_response(str(e), 500)


@router.post("/generation/ppt", summary="Generate PPT file (Combined)")
async def generate_ppt_file(request: CombinedGeneratePPTRequest):
    """
    Combined API: Create task and generate PPT file in one call

    This endpoint combines two AIPPT APIs:
    1. POST /api/ppt/v2/createTask - Creates a task
    2. POST /api/ppt/v2/generatePptx - Generates PPT from task and markdown

    **Task Types:**
    - 1: Smart Generation (theme/requirements) - content required
    - 2: Upload File - not supported in this endpoint
    - 3: Mind Map - not supported in this endpoint
    - 4: Word to PPT - not supported in this endpoint
    - 5: Web Link - content required (http/https URL)
    - 6: Paste Text - content required (up to 20000 chars)
    - 7: Markdown Outline - content required (markdown format)

    Args:
        request: Combined PPT generation request
            - task_type: Type of task (1-7)
            - content: Content for task creation (required for types 1, 5, 6, 7)
            - markdown: Markdown content for PPT generation
            - template_id: Template ID to use for PPT generation

    Returns:
        Complete PPT information including task_id and pptInfo

    Example request:
        {
            "task_type": 6,
            "content": "AI and Machine Learning",
            "markdown": "# AI\\n## Introduction\\n### What is AI\\n- Definition",
            "template_id": "1940697631068151808"
        }
    """
    try:
        # Validate input based on task type
        if request.task_type in [1, 5, 6, 7] and not request.content:
            return create_error_response(
                f"Content is required for task type {request.task_type}",
                400
            )

        if request.task_type in [2, 3, 4]:
            return create_error_response(
                f"Task type {request.task_type} (file upload) is not supported in this endpoint. Please use /generation/task/create instead.",
                400
            )

        service = PPTGenerationService()

        # Step 1: Create task
        task_id = service.create_task_from_text(
            content=request.content,
            task_type=request.task_type
        )

        # Step 2: Generate PPT file
        result = service.generate_ppt_file(
            task_id=task_id,
            markdown=request.markdown,
            template_id=request.template_id
        )

        # Add task_id to response for reference
        if result.get('code') == 0 and result.get('data'):
            result['data']['task_id'] = task_id

        return handle_api_response(result, "PPT file generated successfully")

    except Exception as e:
        return create_error_response(str(e), 500)


@router.post("/generation/create-complete", summary="Create PPT (Complete Workflow)")
async def create_ppt_complete(request: CreatePPTCompleteRequest):
    """
    Complete PPT creation workflow in one call
    Creates task -> Generates content -> Generates PPT file

    Args:
        request: Complete PPT creation request

    Returns:
        Complete result with task ID, content, and PPT information
    """
    try:
        service = PPTGenerationService()
        result = service.create_ppt_from_text(
            content=request.content,
            template_id=request.template_id,
            prompt=request.prompt,
            page_count=request.page_count,
            lang=request.lang
        )

        if 'error' in result:
            return create_error_response(result['error'], 500)

        return create_success_response(result, "PPT created successfully")
    except Exception as e:
        return create_error_response(str(e), 500)


# ==================== PPT Management Routes ====================

@router.get("/ppts", summary="List user PPTs")
async def list_ppts(
    current: int = Query(1, ge=1, description="Current page number"),
    size: int = Query(10, ge=1, le=100, description="Page size")
):
    """
    List user's PPT works with pagination

    Args:
        current: Page number
        size: Page size

    Returns:
        Paginated PPT list
    """
    try:
        service = PPTManagementService()
        result = service.list_user_ppts(current, size)
        return handle_api_response(result, "Successfully retrieved PPT list")
    except Exception as e:
        return create_error_response(str(e), 500)


@router.get("/ppts/{ppt_id}", summary="Get PPT details")
async def get_ppt_details(ppt_id: str):
    """
    Get complete PPT data

    Args:
        ppt_id: PPT ID

    Returns:
        Complete PPT information
    """
    try:
        service = PPTManagementService()
        result = service.get_ppt_details(ppt_id)
        return handle_api_response(result, "Successfully retrieved PPT details")
    except Exception as e:
        return create_error_response(str(e), 500)


@router.get("/ppts/{ppt_id}/download", summary="Get PPT download URL")
async def download_ppt(ppt_id: str):
    """
    Get download URL for PPT file

    Args:
        ppt_id: PPT ID

    Returns:
        Download URL
    """
    try:
        service = PPTManagementService()
        download_url = service.download_ppt(ppt_id)
        return create_success_response(
            {"download_url": download_url},
            "Download URL retrieved successfully"
        )
    except Exception as e:
        return create_error_response(str(e), 500)


@router.delete("/ppts/{ppt_id}", summary="Delete PPT")
async def delete_ppt(ppt_id: str):
    """
    Delete a PPT

    Args:
        ppt_id: PPT ID

    Returns:
        Success message
    """
    try:
        service = PPTManagementService()
        success = service.delete_ppt(ppt_id)
        if success:
            return create_success_response(None, "PPT deleted successfully")
        else:
            return create_error_response("Failed to delete PPT", 500)
    except Exception as e:
        return create_error_response(str(e), 500)
